package org.geektimes.interceptor.jdk;

import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.geektimes.interceptor.ChainableInvocationContext;
import org.geektimes.interceptor.ReflectiveMethodInvocationContext;

/**
 * {@link Interceptor @Interceptor} enhancer by JDK Dynamic Proxy .
 * <br> @author leo
 * <br> @date 2021/7/27
 * <br> @since 1.0.0
 */
public class JdkProxyEnhancer implements InvocationHandler {

    private final Object target;

    /**
     * {@link javax.interceptor.Interceptor}
     */
    private final Object [] interceptors;

    public JdkProxyEnhancer(Object target, Object[] interceptors) {
        this.target = target;
        this.interceptors = interceptors;
    }

    public Object invoke(Class<?> interfaceClass) {
        return Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class[]{interfaceClass},this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        InvocationContext delegateContext = new ReflectiveMethodInvocationContext(target,method,args);
        ChainableInvocationContext context = new ChainableInvocationContext(delegateContext,this.interceptors);
        return context.proceed();
    }
}
